package com.atguigu.srb.core.service.impl;

import com.atguigu.srb.base.util.Asserts;
import com.atguigu.srb.base.util.JwtUtils;
import com.atguigu.srb.common.result.ResponseEnum;
import com.atguigu.srb.core.entity.UserAccount;
import com.atguigu.srb.core.entity.UserBind;
import com.atguigu.srb.core.entity.UserInfo;
import com.atguigu.srb.core.entity.vo.UserBindHfbVO;
import com.atguigu.srb.core.hfb.FormHelper;
import com.atguigu.srb.core.hfb.HfbConst;
import com.atguigu.srb.core.hfb.RequestHelper;
import com.atguigu.srb.core.mapper.UserBindMapper;
import com.atguigu.srb.core.service.UserAccountService;
import com.atguigu.srb.core.service.UserBindService;
import com.atguigu.srb.core.service.UserInfoService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 用户绑定表 服务实现类
 * </p>
 *
 * @author Atguigu
 * @since 2023-06-30
 */
@Service
public class UserBindServiceImpl extends ServiceImpl<UserBindMapper, UserBind> implements UserBindService {
    @Resource
    UserInfoService userInfoService;
    @Resource
    UserAccountService userAccountService;
    @Override
    public String bindAccount(String token, UserBindHfbVO userBindHfbVO) {
        //1.将绑定数据保存到userBind表中,并且将用户的绑定状态设置为未完成
        //1.1首先需要根据token获取用户的userId,这是用户身份的唯一标示
        Long userId = JwtUtils.getUserId(token);
        //1.2根据userId到userBind中查询用户的信息,后面需要判断是第一次绑定还是需要修改信息
        UserBind userBind = getUserBind(userId);
        //1.3判断查询出来的userBind是否为空
        if(userBind == null){
            //进来这里面,说明是第一次绑定账户,需要执行新增的操作
            //第一次,没有userId,需要设置userId
            userBind = new UserBind();
            BeanUtils.copyProperties(userBindHfbVO,userBind);
            userBind.setUserId(userId);
            //需要将用户的绑定状态设置为未完成 绑定状态（0：未绑定，1：绑定成功 -1：绑定失败）
            userBind.setStatus(0);
            this.save(userBind);
        }else{
            //说明已经开过户了,需要执行修改的操作
            BeanUtils.copyProperties(userBindHfbVO,userBind);
            this.updateById(userBind);
        }
        //2.构建可以让用户跳转到hfb开户的页面的响应(而且携带hfb对应接口需要的参数)
        //url(hfb处理用户绑定请求的接口的地址) paramsMap(需要的一系列参数)
        Map<String,Object> paramsMap = new HashMap<>();
        paramsMap.put("agentId",HfbConst.AGENT_ID);//给商户分配的唯一标识
        paramsMap.put("agentUserId",userId);//商户的个人会员ID,由数字,字母组成
        paramsMap.put("idCard",userBindHfbVO.getIdCard());//身份证号
        paramsMap.put("personalName",userBindHfbVO.getName());//用户的真实姓名
        paramsMap.put("bankType",userBindHfbVO.getBankType());//银行类型
        paramsMap.put("bankNo",userBindHfbVO.getBankNo());//银行卡号
        paramsMap.put("mobile",userBindHfbVO.getMobile());//银行预留的手机号码
        // paramsMap.put("email",);//这个不是必须的
        paramsMap.put("returnUrl","http://localhost:3000/user");//绑定完成后同步返回商户的完整的地址
        paramsMap.put("notifyUrl","http://192.168.216.100/api/core/userBind/callback");//绑定完成后异步通知商户的完整地址
        paramsMap.put("timestamp", System.currentTimeMillis());//时间戳,毫秒数
        String sign = RequestHelper.getSign(paramsMap);//通过工具类生成验签参数
        paramsMap.put("sign",sign);//验签参数 需要按照文档中的方法生成签名,保证数据不会被篡改
        String s = FormHelper.buildForm(HfbConst.USERBIND_URL, paramsMap);
        return s;
    }

    private UserBind getUserBind(Long userId) {
        UserBind userBind = this.getOne(Wrappers.lambdaQuery(UserBind.class).eq(UserBind::getUserId, userId));
        return userBind;
    }

    //涉及多个数据库的操作,所以这个地方需要开启事物处理的功能
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String callback(Map<String, Object> map) {
        //1.如果获取到的响应为空,或者resultCode状态不正确,直接抛出异常
        Asserts.AssertTrue(map.get("resultCode") == "0001" || map.get("resultCode") != null, ResponseEnum.HFB_BIND_FAIL);
        //2.验证签名
        Asserts.AssertTrue(RequestHelper.isSignEquals(map),ResponseEnum.WEIXIN_CALLBACK_PARAM_ERROR);
        //3.验证OK之后设置参数,更改user_bind, user_info,account表格
        UserBind userBind = getUserBind(Long.parseLong(map.get("agentUserId").toString()));
        userBind.setBindCode((String)map.get("bindCode"));
        userBind.setStatus(1); //将状态修改为已绑定
        //3.1更新user_bind表
        this.updateById(userBind);
        //3.2更新user_info表
        userInfoService.update(Wrappers.lambdaUpdate(UserInfo.class)
                .eq(UserInfo::getId,Long.parseLong(map.get("agentUserId").toString()))
                .set(UserInfo::getName, userBind.getName())
                .set(UserInfo::getIdCard,userBind.getIdCard())
                .set(UserInfo::getBindStatus,userBind.getStatus())
                .set(UserInfo::getBindCode,userBind.getBindCode())
                //这种方式更新,时间日期自动填充器不会起作用,所以需要我们自己手动的生成更新的时间
                .set(UserInfo::getUpdateTime,new Date()));
        //3.3更新account表
        UserAccount userAccount = new UserAccount();
        userAccount.setAmount(new BigDecimal(0));
        userAccount.setFreezeAmount(new BigDecimal(0));
        userAccount.setUserId(Long.parseLong(map.get("agentUserId").toString()));
        userAccountService.save(userAccount);
        //必须响应这个,否则hfb会重试几乎5次,发送成功的通知结果
        return "success";
    }
}
